package com.stgy.lease.web.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stgy.lease.common.exception.StgyException;
import com.stgy.lease.common.result.ResultCodeEnum;
import com.stgy.lease.common.utils.JwtUtil;
import com.stgy.lease.model.domain.SystemUser;
import com.stgy.lease.web.admin.dto.AdminUserLoginDto;
import com.stgy.lease.web.admin.dto.SystemUserSearchDto;
import com.stgy.lease.web.admin.service.SystemPostService;
import com.stgy.lease.web.admin.service.SystemUserService;
import com.stgy.lease.web.admin.mapper.SystemUserMapper;
import com.stgy.lease.web.admin.vo.AdminCaptchaVo;
import com.wf.captcha.GifCaptcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author lingx
 * @description 针对表【system_user(员工信息表)】的数据库操作Service实现
 * @createDate 2024-08-28 11:00:30
 */
@Service
public class SystemUserServiceImpl extends ServiceImpl<SystemUserMapper, SystemUser>
        implements SystemUserService {

    @Autowired
    private SystemPostService systemPostService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //条件分页查询管理员列表
    @Override
    public Page<SystemUser> getPage(SystemUserSearchDto searchDto) {
        Page<SystemUser> page = this.page(searchDto.getPage(SystemUser.class),
                Wrappers.lambdaUpdate(SystemUser.class)
                        .like(StringUtils.hasLength(searchDto.getName()),
                                SystemUser::getName, searchDto.getName())
                        .like(StringUtils.hasLength(searchDto.getPhone()),
                                SystemUser::getPhone, searchDto.getPhone()));
        page.getRecords().forEach(systemUser -> {
            //查询每个管理员的岗位信息
            systemUser.setPostName(systemPostService.getById(systemUser.getPostId()).getName());
        });
        return page;
    }

    //校验用户名是否存在
    @Override
    public boolean exists(String username) {
        LambdaQueryWrapper<SystemUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SystemUser::getUsername, username);
        wrapper.last("limit 1");
        SystemUser one = this.getOne(wrapper);
        return one == null;
    }

    //新增或更新用户
    @Override
    public boolean saveOrUpdateSystemUser(SystemUser systemUser) {
        try {
            SystemUser one = this.getOne(Wrappers.lambdaQuery(SystemUser.class)
                    .eq(SystemUser::getUsername, systemUser.getUsername())
                    .or()
                    .eq(SystemUser::getPhone, systemUser.getPhone())
                    .last("limit 1"));
            //账号存在 并且 id不相等
            if (one != null && !one.getId().equals(systemUser.getId())) {
                throw new StgyException(ResultCodeEnum.DATA_EXISTS_ERROR);
            }
            //新增时设置默认头像
            if (systemUser.getId() == null) {
                systemUser.setAvatarUrl("https://th.bing.com/th/id/OIP.IEaB8zcZQ2j15HIiL2JPmAHaIo?w=150&h=180&c=7&r=0&o=5&pid=1.7");
                systemUser.setStatus(1);
            }
            //密码加密 以后的加密可以使用 加盐(salt 就是一个随机的字符串)的方式来处理
            String md5DigestAsHex = DigestUtils.md5DigestAsHex(systemUser.getPassword().getBytes(StandardCharsets.UTF_8));
            systemUser.setPassword(md5DigestAsHex);


            return this.saveOrUpdate(systemUser);
        } catch (Exception e) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR, e);
        }
    }

    //获取登录验证码
    @Override
    public AdminCaptchaVo getCaptcha() {
        //1、生成验证码
        GifCaptcha gifCaptcha = new GifCaptcha(120, 40, 4);
        //2、组装响应对象
        AdminCaptchaVo adminCaptchaVo = new AdminCaptchaVo();
        adminCaptchaVo.setImage(gifCaptcha.toBase64());
        String key = UUID.randomUUID().toString().replace("-", "");
        adminCaptchaVo.setKey(key);
        //gifCaptcha.text()
        //3、redis缓存验证码
        stringRedisTemplate.opsForValue().set("stgy:admin:code:" + key, gifCaptcha.text(), 5, TimeUnit.MINUTES);
        return adminCaptchaVo;
    }

    //管理员登录
    @Override
    public String login(AdminUserLoginDto loginDto) {
        if (StringUtils.isEmpty(loginDto)) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR);
        }
        String username = loginDto.getUsername();
        String password = loginDto.getPassword();
        String captchaCode = loginDto.getCaptchaCode();
        String captchaKey = loginDto.getCaptchaKey();
        //校验参数不为空
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password) ||
                StringUtils.isEmpty(captchaCode) || StringUtils.isEmpty(captchaKey)) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR);
        }
        //1、接收前端提交的参数，获取redis缓存的验证码校验 不区分大小写
        String code = stringRedisTemplate.opsForValue().get("stgy:admin:code:" + captchaKey);
        if (!captchaCode.equalsIgnoreCase(code)) {
            throw new StgyException(ResultCodeEnum.ADMIN_CAPTCHA_CODE_ERROR);
        }
        //2、根据账号查询用户信息
        SystemUser one = this.getOne(Wrappers.lambdaQuery(SystemUser.class)
                .eq(SystemUser::getUsername, username)
                .last("limit 1"));
        if (ObjectUtils.isEmpty(one)) {
            throw new StgyException(ResultCodeEnum.ADMIN_ACCOUNT_NOT_EXIST_ERROR);
        }
        //3、对密码加密和查询到的用户密码比较
        password = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
        if (!password.equals(one.getPassword())) {
            throw new StgyException(ResultCodeEnum.ADMIN_ACCOUNT_ERROR);
        }
        //4、删除redis缓存的验证码
        stringRedisTemplate.delete("stgy:admin:code:" + captchaKey);
        //5、将用户信息脱敏 封装为token返回
        String token = JwtUtil.createToken(one);
        return token;
    }
}




